package com.dataseek.iot.mqtt.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dataseek.iot.core.constant.AlarmConst;
import com.dataseek.iot.core.constant.TopicConst;
import com.dataseek.iot.core.enums.AlarmType;
import com.dataseek.iot.mqtt.handler.MessageHandler;
import com.dataseek.iot.mqtt.service.MqttReceiveService;
import com.dataseek.iot.mqtt.vo.MsgVo;
import com.dataseek.iot.mysql.entity.Device;
import com.dataseek.iot.mysql.service.impl.DeviceServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.dataseek.iot.mqtt.constant.MqttConstant.*;


/**
 * @author cc
 * @Title: 默认数据处理服务
 * @Description: 默认数据处理服务
 * @date 2021/9/244:24 下午
 * @since 1.0
 */
@Service
@Slf4j
public class DefaultMqttReceiveService implements MqttReceiveService {


    @Autowired
    MessageHandler messageHandler;

    @Autowired
    DefaultMqttGateway mqttGateway;

    @Autowired
    DeviceServiceImpl deviceService;

    @Value("${mqtt.publisher.clientId}")
    private String clientId;

    @Value("${mqtt.subscriber.propTopic}")
    private String propTopic;

    @Override
    public void handlerMqttMessage(String topic, String data) {
        //TODO 处理

        String[] topicParams = topic.split("/");
        if(topicParams.length==1){
            log.info(data);
        }
        String deviceCode;

        if(topic.contains(OFFLINE)||topic.contains(ONLINE)){
            log.error("设备"+ topicParams[0] + data);
            return;
        }

        if(topic.contains(SYSDESCR)){
            return;
        }
        /**
         * 如果是是上线下线消息，要单独获取设备编码
         */
        if(topic.contains(DISCONNECTED)||topic.contains(CONNECTED)){
            deviceCode = topicParams[topicParams.length-2].trim();
            JSONObject jsonData = JSON.parseObject(data);
            Device d;
            try {
                d = deviceService.getDeviceByCode(deviceCode);
                jsonData.put("deviceCode", deviceCode);
                jsonData.put("deviceName", d.getDeviceName());
            }catch (Exception e) {
                log.error("查询设备失败，请校对编码为 {} 的设备是否存在", deviceCode);
                return;
            }
            if(Objects.nonNull(d)){
                handleMsgByTopic(topic, d, jsonData.toJSONString());
            }
        }else {
            String [] propTopics = propTopic.split(",");
            List<String> topics = Arrays.asList(propTopics);
            for(String s : topics){
                if(topic.contains(s)){
                    deviceCode = topicParams[2];
                    JSONObject jsonData = JSON.parseObject(data);
                    Device d = null;
                    try {
                        d = deviceService.getDeviceByCode(deviceCode);
                        jsonData.put("deviceCode", deviceCode);
                        jsonData.put("deviceName", d.getDeviceName());
                    }catch (Exception e) {
                        log.error("查询设备失败，请校对编码为 {} 的设备是否存在", deviceCode);
                        e.printStackTrace();
                    }
                    if(Objects.nonNull(d)){
                        handleMsgByTopic(topic, d, jsonData.toJSONString());
                    }
                    if(deviceCode.equals(clientId)){
                        log.debug("接收到生产端设备上线{}", clientId);
                        return;
                    }
                }
            }

        }
    }

    /**
     * 根据topic处理消息
     * @param topic
     * @param d
     * @param data
     * @return
     */
    private  void handleMsgByTopic(String topic, Device d, String data){
        StringBuffer sb = new StringBuffer();
        MsgVo msgVo = new MsgVo();
        msgVo.setDeviceCode(d.getDeviceCode());
        sb.append("名称为 ").append(d.getDeviceName()).append(" 编码为 ").append(d.getDeviceCode()).append(" 的设备,");
        //判断是否上报的是参数
        try {
            if(topic.contains(REPORT_PROPS)){
                // 存储到数据库中
                messageHandler.handleDeviceParams(d.getProductCode(), d.getDeviceCode(), data);
                Device device = deviceService.getDeviceByCode(d.getDeviceCode());
                //如果设备为离线状态，则更新为上线
                if(device.getState().equals("-1")){
                    deviceService.updateStateByCode(d.getDeviceCode(), "0");
                }
                sb.append(" 参数详情如下: ").append(data);
                //TODO 接入产品事件信息，进行判断
            }else if(topic.contains(ALARM)){
                //判断上报的是否为报警
                if(data.contains("data")){
                    JSONObject record = JSON.parseObject(data);
                    Map map = (Map) record.get("data");
                    String alarmType = map.get("alarmType").toString();
                    String value = map.get("value").toString();
                    String messageId = record.getString("messageId");
                    if(alarmType.equals(AlarmConst.NO_ALARM)){
                        deviceService.updateStateByCode(d.getDeviceCode(), "0");
                        sb.append("报警恢复");
                        msgVo.setMessage(sb.toString());
                        msgVo.setMessageId(messageId);
                        //向前端通知报警消息
                        mqttGateway.sendToMqtt(TopicConst.NOTICE, JSON.toJSONString(msgVo));
                    }else if(alarmType.equals(AlarmConst.POS_ALARM)){
                        if(map.get("value").equals(0)){
                            //TODO 查询
                            deviceService.updateStateByCode(d.getDeviceCode(), "0");
                            sb.append(" 变位报警恢复");
                            msgVo.setMessage(sb.toString());
                            msgVo.setMessageId(messageId);
                            //向前端通知报警消息
                            mqttGateway.sendToMqtt(TopicConst.NOTICE, JSON.toJSONString(msgVo));
                        }else if(map.get("value").equals(1)){
                            deviceService.updateStateByCode(d.getDeviceCode(), "1");
                            sb.append(" 变位报警");
                            msgVo.setMessage(sb.toString());
                            msgVo.setMessageId(messageId);
                            log.warn(sb.toString());
                            //向前端通知报警消息
                            mqttGateway.sendToMqtt(TopicConst.ALARM, JSON.toJSONString(msgVo));
                        }
                    }else{
                        deviceService.updateStateByCode(d.getDeviceCode(), "1");
                        sb.append(AlarmType.getTextByCode(alarmType))
                                .append(" 报警值为: ")
                                .append(value);
                        msgVo.setMessage(sb.toString());
                        msgVo.setMessageId(messageId);
                        log.warn(sb.toString());
                        //向前端通知报警消息
                        mqttGateway.sendToMqtt(TopicConst.ALARM, JSON.toJSONString(msgVo));
                    }
                    messageHandler.handleAlarmLog(d.getProductCode(), d.getDeviceCode(), data, sb.toString());
                }
                //处理变位报警
            } else if(topic.contains(INVOKE_FUNCTION)){
                sb.append("下发功能指令");
                msgVo.setMessage(sb.toString());
                //向前端通知事件
                mqttGateway.sendToMqtt(TopicConst.EVENT, JSON.toJSONString(msgVo));
                //变位报警恢复
            }else if(topic.contains(REPLY_INVOKE_FUNCTION)){
                //功能指令回复
                log.info("发送功能回复信息为：" + data);
                if(data.contains("success")){
                    JSONObject json = JSON.parseObject(data);
                    Boolean isSuccess = (Boolean) json.get("success");
                    String msg = isSuccess? "执行下发指令成功" : "执行下发指令失败";
                    sb.append(msg);
                    msgVo.setMessage(sb.toString());
                    mqttGateway.sendToMqtt(TopicConst.NOTICE, JSON.toJSONString(msgVo));
                }
                //断连
            }else if(topic.contains(DISCONNECTED)){
                try{
                    deviceService.updateStateByCode(d.getDeviceCode(), "-1");
                    sb.append(" 离线！");
                    messageHandler.handleDisconnectedLog(d.getDeviceCode(), sb.toString());
                    msgVo.setMessage(sb.toString());
                    //向前端通知离线消息
                    mqttGateway.sendToMqtt(TopicConst.NOTICE, JSON.toJSONString(msgVo));
                }catch (Exception e){
                    log.error("更新设备状态失败， 请校对编码为 {} ， 名称为 {} 的设备是否存在", d.getDeviceCode(), d.getDeviceName());
                    e.printStackTrace();
                }
                //判断是否在线
            }else if(topic.contains(CONNECTED)){
                try{
                    deviceService.updateStateByCode(d.getDeviceCode(), "0");
                    sb.append("  上线！");
                    messageHandler.handleConnectedLog(d.getDeviceCode(), sb.toString());
                    //向前端通知上线消息
                    msgVo.setMessage(sb.toString());
                    mqttGateway.sendToMqtt(TopicConst.NOTICE, JSON.toJSONString(msgVo));
                }catch (Exception e){
                    log.error("更新设备状态失败，请校对编码为 {} , 名称为 {} 的设备是否存在", d.getDeviceCode(), d.getDeviceName());
                    e.printStackTrace();
                }
            } else {
                messageHandler.handleNormalLog(d.getDeviceCode(), data);
            }
        }catch (Exception e){
            log.error(e.getMessage());
        }

        log.info("用户消息提示为: {}", sb);
    }


}
